package com.android.bind.components;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import android.app.Activity;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.View;

import com.android.bind.annotation.Listener;

public class EventManager {
	/**
	 * 在Activity中进行方法注入
	 * 
	 * @param activity
	 */
	public static void bindEvents(Activity activity) {
		Method[] methods = getMethods(activity);
		if (methods == null || methods.length == 0) {
			return;
		}
		for (Method method : methods) {
			method.setAccessible(true);
			Annotation[] annotations = method.getDeclaredAnnotations();
			if (annotations == null || annotations.length == 0) {
				continue;
			}
			for (Annotation annotation : annotations) {
				Class<? extends Annotation> annotationType = annotation
						.annotationType();
				int[] viewIds = null;
				try {
					Method valueMethod = annotationType
							.getDeclaredMethod("value");
					viewIds = (int[]) valueMethod.invoke(annotation);
				} catch (Exception e) {
					e.printStackTrace();
				}
				String callback = null;
				try {
					Method valueMethod = annotationType
							.getDeclaredMethod("callback");
					callback = (String) valueMethod.invoke(annotation);
				} catch (Exception e) {
					e.printStackTrace();
				}
				Listener info = annotationType.getAnnotation(Listener.class);
				initListener(activity, method, viewIds, callback, info);
			}

		}
	}

	/**
	 * 在Fragment中进行方法注入
	 * 
	 * @param fragment
	 * @param view
	 */
	public static void bindEvents(Fragment fragment, View view) {
		Method[] methods = getMethods(fragment);
		if (methods == null || methods.length == 0) {
			return;
		}
		for (Method method : methods) {
			method.setAccessible(true);
			Annotation[] annotations = method.getDeclaredAnnotations();
			if (annotations == null || annotations.length == 0) {
				continue;
			}
			for (Annotation annotation : annotations) {
				Class<? extends Annotation> annotationType = annotation
						.annotationType();
				int[] viewIds = null;
				try {
					Method valueMethod = annotationType
							.getDeclaredMethod("value");
					viewIds = (int[]) valueMethod.invoke(annotation);
				} catch (Exception e) {
					e.printStackTrace();
				}
				String callback = null;
				try {
					Method valueMethod = annotationType
							.getDeclaredMethod("callback");
					callback = (String) valueMethod.invoke(annotation);
				} catch (Exception e) {
					e.printStackTrace();
				}
				Listener info = annotationType.getAnnotation(Listener.class);
				initListener(fragment, view, method, viewIds, callback, info);
			}

		}
	}

	/**
	 * 通过反射，获取obj对象所在类的所有声明的方法
	 * 
	 * @param obj
	 * @return
	 */
	private static Method[] getMethods(Object obj) {
		Class<? extends Object> clazz = obj.getClass();
		Method[] methods = clazz.getDeclaredMethods();
		return methods;
	}

	/**
	 * 对Activity中的方法添加代理实现注入调用
	 * 
	 * @param activity
	 * @param method
	 * @param ViewIds
	 * @param info
	 */
	private static void initListener(Activity activity, Method method,
			int[] ViewIds, String call, Listener info) {
		if (info == null) {
			return;
		}
		Class<?> type = info.type();
		String setter = info.set();
		String callback = info.callback();
		if (ViewIds == null || ViewIds.length == 0) {
			return;
		}
		for (int viewId : ViewIds) {
			DynamicHandler handler = new DynamicHandler(activity);
			if (TextUtils.isEmpty(callback) && !TextUtils.isEmpty(call)) {
				handler.addMethod(call, method);
			} else if (TextUtils.isEmpty(call) && !TextUtils.isEmpty(callback)) {
				handler.addMethod(callback, method);
			}
			Object listener = Proxy.newProxyInstance(type.getClassLoader(),
					new Class<?>[] { type }, handler);
			try {
				View view = activity.findViewById(viewId);
				Method bindLietener = view.getClass().getMethod(setter, type);
				bindLietener.invoke(view, listener);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 为Fragment中的方法添加代理，实现方法注入
	 * 
	 * @param fragment
	 * @param contentView
	 * @param method
	 * @param ViewIds
	 * @param info
	 */
	private static void initListener(Fragment fragment, View contentView,
			Method method, int[] ViewIds, String call, Listener info) {
		if (info == null) {
			return;
		}
		Class<?> type = info.type();
		String setter = info.set();
		String callback = info.callback();
		if (ViewIds == null || ViewIds.length == 0) {
			return;
		}
		for (int viewId : ViewIds) {
			DynamicHandler handler = new DynamicHandler(fragment);
			if (TextUtils.isEmpty(callback) && !TextUtils.isEmpty(call)) {
				handler.addMethod(call, method);
			} else if (TextUtils.isEmpty(call) && !TextUtils.isEmpty(callback)) {
				handler.addMethod(callback, method);
			}
			Object listener = Proxy.newProxyInstance(type.getClassLoader(),
					new Class<?>[] { type }, handler);
			try {
				View view = contentView.findViewById(viewId);
				Method bindLietener = view.getClass().getMethod(setter, type);
				bindLietener.invoke(view, listener);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}
